// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "AbilitySystemComponent.h"
#include "AuraAbilitySystemComponent.generated.h"

/**
 *  非动态多播委托不参与引擎的反射系统，它只需要知道参数的类型，而不需要参数的名称。
 *  
 */
DECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssetTagsDelegate, const FGameplayTagContainer&)

/** 携带ASC的委托 */
DECLARE_MULTICAST_DELEGATE_OneParam(FAbilityGiven, UAuraAbilitySystemComponent*)

/** 携带能力实例的委托 */
DECLARE_DELEGATE_OneParam(FForeachAbility, FGameplayAbilitySpec&)


/**
 * 能力系统组件
 */
UCLASS()
class AURA_API UAuraAbilitySystemComponent : public UAbilitySystemComponent
{
	GENERATED_BODY()

public:

	/** 初始化应用技能后，此值将被设置为true，用于记录当前是否被初始化完成 */
	bool bStartupAbilitiesGiven = false;

	/** 技能初始化应用后的回调委托 */
	FAbilityGiven AbilityGivenDelegate;

	/** 效果标签的委托,用于将效果标签广播 */
	FEffectAssetTagsDelegate EffectAssetTagsDelegate;

	/** 能力系统相关工作信息设置 */
	void SetAbilitySystemWorkInfo();

	/** 为角色的ASC添加能力 */
	void AddCharacterAbilities(TArray<TSubclassOf<UGameplayAbility>>& StartUpAbilityClasses);

	/** 为角色添加被动能力 */
	void AddCharacterPassiveAbilities(TArray<TSubclassOf<UGameplayAbility>>& StartUpPassiveAbilityClasses);

	/** 标记的输入触发时,根据输入标签激活对应能力 */
	void AbilityTaggedInputTriggered(const FGameplayTag& InputTag);

	/** 标记的输入松开时,根据输入标签激活对应能力 */
	void AbilityTaggedInputReleased(const FGameplayTag& InputTag);

	/** 传入可携带技能的委托,遍历角色所有可激活能力,携带技能的委托广播出去*/
	void ForeachCharacterAbilities(const FForeachAbility& Delegate);

	/** 从技能规格实例中提取对应的游戏能力标签 */
	static FGameplayTag GetAbilityTagFormSpec(FGameplayAbilitySpec& Spec);

	/** 从技能规格实例中提取对应的输入标签 */
	static FGameplayTag GetInputTagFormSpec(FGameplayAbilitySpec& Spec);

protected:

	virtual void OnRep_ActivateAbilities() override;

private:

	/** 处理 当效果应用后 */
	void HandleEffectApplied(
		UAbilitySystemComponent* ASC, const FGameplayEffectSpec& EffectSpec,
		FActiveGameplayEffectHandle ActiveEffectHandle
	) const;
};
